import React, { useState, useEffect } from "react";
import { useRouter } from "next/router";

import Layout from "~/components/Layout";
import VulnerabilityIcon from "~/components/icons/VulnerabilityIcon";

import { api } from "~/utils/api";
import { CvssBox } from "~/components/vulnerabilityReport/CvssBox";
import { CpeBox } from "~/components/vulnerabilityReport/CpeBox";
import type {
  CveTag,
  LangString,
  Metrics,
  Reference,
  CveItem,
} from "~/server/api/routers/vulnerability";
import { SeverityGage } from "~/components/vulnerabilityReport/SeverityGauge";
import { ThreatBar } from "~/components/vulnerabilityReport/ThreatBar";
import ReactMarkdown from "react-markdown";
import VulnerabilityTabs from "~/components/vulnerability/VulnerabilityTabs";
import AffectedSystems from "~/components/vulnerability/AffectedSystems";
import Remediation from "~/components/vulnerability/Remediation";
import { cn } from "~/components/lib/utils";

// Define tab types
type TabType = "summary" | "nvd-details" | "affected-systems" | "remediation";

const Vulnerability = () => {
  const [activeTab, setActiveTab] = useState<TabType>("summary");
  const router = useRouter();
  const vulnId = router.query.id as string;

  // Fetch vulnerability data
  const {
    data: rawData,
    isLoading,
    isError,
  } = api.vulnerability.getVulnerability.useQuery(
    { id: vulnId },
    { enabled: !!vulnId }
  );

  const vulnData = rawData ?? emptyCVEItem;
  const cvssScore =
    vulnData?.metrics?.cvssMetricV31?.[0]?.cvssData.baseScore ?? 0;

  // Mock affected hosts data - in a real implementation this would come from an API call
  const affectedHostsCount = 3; // This would dynamically come from backend data

  const handleTabChange = (tab: TabType) => {
    setActiveTab(tab);
  };

  // Loading state
  if (isLoading) {
    return (
      <Layout>
        <div className="flex h-64 items-center justify-center">
          <div className="h-8 w-8 animate-spin rounded-full border-b-2 border-t-2 border-violet-500"></div>
          <span className="ml-2">Loading vulnerability information...</span>
        </div>
      </Layout>
    );
  }

  // Error state
  if (isError) {
    return (
      <Layout>
        <div className="container mx-auto px-4 py-6">
          <div className="rounded-lg border border-red-200 bg-red-50 p-6 text-red-700 dark:border-red-700 dark:bg-red-900/20 dark:text-red-400">
            <h2 className="mb-4 text-xl font-bold">Vulnerability Not Found</h2>
            <p className="mb-4">
              Could not find vulnerability with ID: {vulnId}
            </p>
            <div className="flex gap-4">
              <button
                className="rounded-md bg-red-100 px-4 py-2 text-red-800 hover:bg-red-200 dark:bg-red-900/30 dark:text-red-300 dark:hover:bg-red-900/50"
                onClick={() => router.back()}
              >
                Go Back
              </button>
              <button
                className="rounded-md bg-violet-500 px-4 py-2 text-white hover:bg-violet-600 dark:bg-violet-600 dark:hover:bg-violet-700"
                onClick={() => router.push("/vulnerabilities")}
              >
                View All Vulnerabilities
              </button>
            </div>
          </div>
        </div>
      </Layout>
    );
  }

  return (
    <Layout>
      <div className="container relative z-20 mb-5">
        {/* Header with mobile responsiveness */}
        <div className="z-10 flex flex-col items-start justify-between space-y-4 sm:flex-row sm:items-center sm:space-y-0">
          <div className="flex items-center">
            <div className="flex dark:fill-white">
              <VulnerabilityIcon width="35px" height="35px" fill="white" />
            </div>
            <h1 className="ml-3 flex text-2xl font-extralight sm:text-4xl">
              {vulnData.id}
            </h1>
          </div>

          {/* Action buttons */}
          <div className="flex gap-2">
            <a
              href={`https://nvd.nist.gov/vuln/detail/${vulnData.id}`}
              target="_blank"
              rel="noopener noreferrer"
              className="flex items-center rounded-md border border-gray-600 px-3 py-1.5 text-sm hover:bg-gray-700 dark:border-gray-700"
            >
              <svg
                className="mr-1.5 h-4 w-4"
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
                <polyline points="15 3 21 3 21 9"></polyline>
                <line x1="10" y1="14" x2="21" y2="3"></line>
              </svg>
              View in NVD
            </a>
            <button
              className="flex items-center rounded-md border border-gray-600 px-3 py-1.5 text-sm hover:bg-gray-700 dark:border-gray-700"
              onClick={() => window.print()}
            >
              <svg
                className="mr-1.5 h-4 w-4"
                xmlns="http://www.w3.org/2000/svg"
                width="24"
                height="24"
                viewBox="0 0 24 24"
                fill="none"
                stroke="currentColor"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
              >
                <polyline points="6 9 6 2 18 2 18 9"></polyline>
                <path d="M6 18H4a2 2 0 0 1-2-2v-5a2 2 0 0 1 2-2h16a2 2 0 0 1 2 2v5a2 2 0 0 1-2 2h-2"></path>
                <rect x="6" y="14" width="12" height="8"></rect>
              </svg>
              Print Report
            </button>
          </div>
        </div>

        <div className="pt-6">
          {/* Revert to original flexbox layout */}
          <div className="flex flex-row">
            <div className="flex h-48 w-72 flex-col">
              <SeverityGage data={vulnData} />
            </div>
            <div className="font-roboto flex flex-row px-2 md:mt-6 md:gap-4">
              <div className="flex flex-col">
                <div className="text-xs uppercase tracking-wider text-gray-400">
                  CVSS BASE SCORE
                </div>
                <CvssBox score={cvssScore} data={vulnData} />
              </div>
              <div className="flex flex-col">
                <div className="text-xs uppercase tracking-wider text-gray-400">
                  VENDOR
                </div>
                <CpeBox cve={vulnData} mobile={false} />
              </div>
              <div className="flex flex-col">
                <div className="text-xs uppercase tracking-wider text-gray-400">
                  AFFECTED SYSTEMS
                </div>
                <div className="mt-2 flex items-center">
                  <span className="text-2xl font-bold">
                    {affectedHostsCount}
                  </span>
                  <div className="ml-2">
                    <div className="rounded-full bg-violet-100 px-2 py-0.5 text-xs font-medium text-violet-800 dark:bg-violet-900/20 dark:text-violet-300">
                      {affectedHostsCount === 1 ? "Host" : "Hosts"}
                    </div>
                    <button
                      onClick={() => setActiveTab("affected-systems")}
                      className="mt-1 text-xs text-violet-600 hover:underline dark:text-violet-400"
                    >
                      View details →
                    </button>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>

        {/* Tab navigation with normalized typography */}
        <div className="relative z-30 mt-8">
          <VulnerabilityTabs
            activeTab={activeTab}
            onTabChange={handleTabChange}
            affectedSystemsCount={affectedHostsCount}
          />

          {/* Tab Content with consistent typography */}
          <div className="mt-6">
            {activeTab === "summary" && <SummaryView cve={vulnData} />}
            {activeTab === "nvd-details" && <NVDView cve={vulnData} />}
            {activeTab === "affected-systems" && (
              <AffectedSystems cve={vulnData} />
            )}
            {activeTab === "remediation" && <Remediation cve={vulnData} />}
          </div>
        </div>
      </div>
    </Layout>
  );
};

interface NVDViewProps {
  cve: CveItem;
}

export const NVDView: React.FC<NVDViewProps> = ({ cve }) => {
  const flattenStringArrays = (arrs: string[][]) =>
    arrs.map((arr) => arr.join(", ")).join("\n");

  /** Convert array of LangString => "en: Some text\nfr: Some text" */
  const flattenLangStrings = (langStrings: LangString[] = []) =>
    langStrings.map((ls) => `${ls.lang}: ${ls.value}`).join("\n");

  /** Convert references => each row's url, plus optional tags. */
  const flattenReferences = (refs: Reference[] = []) =>
    refs
      .map((ref) => {
        const tagString = ref.tags?.length ? ` [${ref.tags.join(", ")}]` : "";
        return `${ref.url}${tagString}`;
      })
      .join("\n");

  /** Convert cveTags => each row "sourceIdentifier: [tag1, tag2]" */
  const flattenCveTags = (cveTags: CveTag[] = []) =>
    cveTags
      .map((tag) => `${tag.sourceIdentifier}: ${tag.tags.join(", ")}`)
      .join("\n");

  /**
   * Flatten metrics. This can be as detailed or minimal as you want.
   * For brevity, we'll just show the baseScore + baseSeverity if available.
   */
  const flattenMetrics = (metrics?: Metrics) => {
    if (!metrics) return "";
    // For demonstration, let's handle just v3.1 metrics.
    // You could add more lines for v4.0, v3.0, v2, etc.
    const v31 = metrics.cvssMetricV31 ?? [];
    const lines = v31.map((m) => {
      const data = m.cvssData;
      return `Source: ${m.source}, Score: ${data.baseScore}, Severity: ${data.baseSeverity}`;
    });
    return lines.join("\n");
  };

  /** A generic table renderer for [string, string] pairs. */
  const renderTable = (headers: string[], data: string[][]) => {
    return (
      <tbody>
        {data.map((row, index) => (
          <tr
            key={index}
            className="h-14 border-b border-gray-300 dark:border-gray-600"
          >
            {headers.map((header, i) => (
              <td
                key={i}
                className="pr-4 text-sm text-gray-600 dark:text-gray-400"
              >
                {row[i]}
              </td>
            ))}
          </tr>
        ))}
      </tbody>
    );
  };

  // Build up your big array of [Attribute, Value] pairs.
  // Omit or rearrange as needed.
  const cveDetails: [string, string][] = [
    ["ID", cve.id],
    ["Severity", `${cve.metrics?.cvssMetricV31?.[0]?.cvssData.baseSeverity}`],
    ["CVSSv3 Score", `${cve.metrics?.cvssMetricV31?.[0]?.cvssData.baseScore}`],
    [
      "CPE",
      (cve.configurations ?? [])
        .map((config) => {
          return config.nodes
            .map((node) => {
              return (node.cpeMatch ?? [])
                .map((cpe) => `${cpe.criteria}`)
                .join(", ");
            })
            .join("\n");
        })
        .join("\n"),
    ],
    ["Source Identifier", cve.sourceIdentifier],
    ["Published", cve.published],
    ["Last Modified", cve.lastModified],
    ["Status", cve.vulnStatus],
    ["Evaluator Comment", cve.evaluatorComment ?? ""],
    ["Evaluator Solution", cve.evaluatorSolution ?? ""],
    ["Evaluator Impact", cve.evaluatorImpact ?? ""],
    ["CISA Exploit Add", cve.cisaExploitAdd ?? ""],
    ["CISA Action Due", cve.cisaActionDue ?? ""],
    ["CISA Required Action", cve.cisaRequiredAction ?? ""],
    ["CISA Vulnerability Name", cve.cisaVulnerabilityName ?? ""],
    ["Descriptions", flattenLangStrings(cve.descriptions)],
    ["Metrics", flattenMetrics(cve.metrics)],
    ["References", flattenReferences(cve.references)],
    ["Tags", flattenCveTags(cve.cveTags)],
    // Weaknesses => e.g. "source: Some source, type: Some type"
    [
      "Weaknesses",
      (cve.weaknesses ?? [])
        .map((w) => {
          const desc = flattenLangStrings(w.description);
          return `${w.source} [${w.type}]\n${desc}`;
        })
        .join("\n\n"),
    ],
    // Configurations => quick flatten
    // Vendor Comments => flatten
    [
      "Vendor Comments",
      (cve.vendorComments || [])
        .map(
          (vc) =>
            `${vc.organization}: ${vc.comment} [LastMod: ${vc.lastModified}]`
        )
        .join("\n"),
    ],
  ];

  return (
    <div className="rounded-lg border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-800">
      <div className="font-orbitron mb-4 text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400">
        NVD Details
      </div>
      <table className="w-full">
        {renderTable(["Attribute", "Value"], cveDetails)}
      </table>
    </div>
  );
};

const SummaryView = ({ cve }: { cve: CveItem }) => {
  const description =
    cve.descriptions?.[0]?.value ?? "No description available";

  return (
    <div className="space-y-6">
      <div className="rounded-lg border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-800">
        <div className="font-orbitron mb-3 text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400">
          Description
        </div>
        <div className="prose prose-sm dark:prose-invert max-w-none">
          <ReactMarkdown>{description}</ReactMarkdown>
        </div>
      </div>

      <div className="rounded-lg border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-800">
        <div className="font-orbitron mb-3 text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400">
          Threat Analysis
        </div>
        <ThreatBar cve={cve} />
      </div>

      <div className="rounded-lg border border-gray-200 bg-white p-6 dark:border-gray-700 dark:bg-gray-800">
        <div className="font-orbitron mb-3 text-xs font-bold uppercase tracking-wider text-gray-500 dark:text-gray-400">
          References
        </div>
        <div className="text-md">
          {cve.references?.length ? (
            <ul className="space-y-2">
              {cve.references?.map((ref) => (
                <li
                  key={ref.url}
                  className="border-b border-gray-100 pb-2 last:border-0 dark:border-gray-700"
                >
                  <a
                    href={ref.url}
                    target="_blank"
                    rel="noreferrer"
                    className="inline-flex items-center text-violet-600 hover:text-violet-800 hover:underline dark:text-violet-400 dark:hover:text-violet-300"
                  >
                    {ref.url.split("//")[1]}
                    <svg
                      className="ml-1 h-3 w-3"
                      xmlns="http://www.w3.org/2000/svg"
                      fill="none"
                      viewBox="0 0 24 24"
                      stroke="currentColor"
                    >
                      <path
                        strokeLinecap="round"
                        strokeLinejoin="round"
                        strokeWidth={2}
                        d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"
                      />
                    </svg>
                  </a>
                </li>
              ))}
            </ul>
          ) : (
            <p className="text-gray-500 dark:text-gray-400">
              No references available.
            </p>
          )}
        </div>
      </div>
    </div>
  );
};

const emptyCVEItem: CveItem = {
  id: "",
  sourceIdentifier: "",
  vulnStatus: "",
  published: "",
  lastModified: "",
  cveTags: [],
  descriptions: [],
  references: [],
  weaknesses: [],
  configurations: [],
  vendorComments: [],
  metrics: {
    cvssMetricV40: [],
    cvssMetricV31: [],
    cvssMetricV30: [],
    cvssMetricV2: [],
  },
};

export default Vulnerability;
